﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Light.Framework.Contract;
using Castle.ActiveRecord.Framework;
using Castle.ActiveRecord;
using System.Configuration;
using System.Reflection;
using Light.Framework.Model;
using NHibernate;
using Light.Framework.Component;
using NHibernate.Criterion;
using Light.Utility;
using Castle.ActiveRecord.Framework.Config;
using System.Collections;

namespace Light.Framework.Castle
{
    /// <summary>
    /// 服务器端处理中心
    /// </summary>
    public class ServerApplication
    {
        private static Role _guest = null;
        private static Logger _logger = null;
        private static IFactory _componentFactory = null;

        static ServerApplication()
        {
        }

        public static ICache Cache { get { return new SysCache(); } }

        /// <summary>
        /// 是否为永久使用权（默认是）
        /// </summary>
        public static bool IsPermanent
        {
            get
            {
                return ApplicationSetting.ReadAppSetting("isPermanent", true);
            }
        }

        /// <summary>
        /// 当前登录用户
        /// </summary>
        public static IUser User
        {
            get
            {
                IUser user = null;
                if (WebHelper.CurContext != null)
                    user = WebHelper.GetSession<IUser>("Current_User");
                else
                    user = Cache.Get("Current_User") as IUser;

                DateTime dt = WebHelper.GetSession<DateTime>("GetTokenTime", default(DateTime));

                //当Session丢失后，尝试用令牌获取当前用户，避免匿名用户恶意访问，加10s间隔限制
                if (user == null &&
                    (dt == default(DateTime) || dt.AddSeconds(10) <= DateTime.Now)
                    )
                {
                    IUserComponent comp = ServerApplication.ComponentFactory.Create<IUserComponent>();
                    string token = WebHelper.GetRequest("token", WebHelper.GetAccessToken());
                    user = comp.GetUserByToken(token);

                    WebHelper.SetSession("Current_User", user);
                    WebHelper.SetSession("GetTokenTime", DateTime.Now);
                }

                return user;
            }
            set
            {
                if (WebHelper.CurContext != null)
                    WebHelper.SetSession("Current_User", value);
                else
                    Cache.Add("Current_User", value);
            }

        }

        /// <summary>
        /// 当前组织机构
        /// </summary>
        public static Organization Organization
        {
            get
            {
                if (User != null)
                    return User.Organization;
                else
                    return null;
            }

        }

        /// <summary>
        /// 访客角色
        /// </summary>
        public static Role Guest
        {
            get
            {
                if (_guest == null)
                {
                    _guest = EntityMediator<Role>.FindOneOrDefault(Expression.Eq("Name", "Guest"));
                }
                return _guest;
            }
        }

        /// <summary>
        /// 当前数据库类型
        /// </summary>
        public static Database Database
        {
            get
            {
                return SQLManager.GetDatabase(SQLManager.GetDbConnection());
            }
        }

        /// <summary>
        /// 组件工厂
        /// </summary>
        public static IFactory ComponentFactory
        {
            get { return ServerApplication._componentFactory; }
            set { ServerApplication._componentFactory = value; }
        }

        /// <summary>
        /// 初始化实体类库
        /// </summary>
        /// <param name="modelAssemblyName">实体类程序集名称</param>
        public static void Initialize(params string[] modelAssemblyNames)
        {

            InitializeActiveRecord(modelAssemblyNames);

            if (_componentFactory == null)
                _componentFactory = new ComponentFactory();
        }

        private static void InitializeActiveRecord(params string[] modelAssemblyNames)
        {
            List<Type> listModels = new List<Type>();

            foreach (var modelAssemblyName in modelAssemblyNames)
            {
                Assembly assembly = Assembly.Load(modelAssemblyName);
                foreach (var t in assembly.GetTypes())
                {
                    string typeNamespace = !String.IsNullOrEmpty(t.Namespace) ? t.Namespace.ToUpper() : "";
                    if (typeNamespace.Contains("MODEL"))
                        listModels.Add(t);
                }
            }

            Assembly assemblyBase = Assembly.Load("Light.Framework");

            foreach (var t in assemblyBase.GetTypes())
            {
                string typeNamespace = !String.IsNullOrEmpty(t.Namespace) ? t.Namespace.ToUpper() : "";
                if (typeNamespace.Contains("MODEL"))
                    listModels.Add(t);
            }

            IConfigurationSource source = null;


            #region 获取数据库配置信息

            try
            {
                source = (IConfigurationSource)ConfigurationManager.GetSection("activerecord");
            }
            catch (ConfigurationErrorsException ex)
            {
                source = GetDefaultConfig();
            }
            if (source == null)
            {
                source = GetDefaultConfig();
            }

            #endregion

            ActiveRecordStarter.Initialize(source, listModels.ToArray());
        }

        private static IConfigurationSource GetDefaultConfig()
        {
            IConfigurationSource source = new InPlaceConfigurationSource();

            IDictionary<string, string> properties = new Dictionary<string, string>();

            properties.Add("connection.isolation", "ReadCommitted");
            properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
            properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
            properties.Add("cache.provider_class", "NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache");
            properties.Add("hbm2ddl.keywords", "none");

            bool isNetwork = ApplicationSetting.ReadAppSetting("isNetwork", false);
            if (!isNetwork)
            {
                properties.Add("connection.driver_class", ApplicationSetting.ReadAppSetting("connection.driver_class", "NHibernate.Driver.FirebirdClientDriver"));
                properties.Add("dialect", ApplicationSetting.ReadAppSetting("dialect", "NHibernate.Dialect.FirebirdDialect"));
                properties.Add("connection.connection_string", ApplicationSetting.ReadAppSetting("connection.connection_string", "ServerType=Embedded;Character Set=NONE;Dialect=3; IsolationLevel=ReadCommitted; User ID=sysdba;Password=masterkey;Initial Catalog=Data\\DB.FDB;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=5000;Packet Size=8192;"));
            }
            else
            {
                properties.Add("connection.driver_class", ApplicationSetting.ReadAppSetting("connection.driver_class", "NHibernate.Driver.MySqlDataDriver"));
                properties.Add("dialect", ApplicationSetting.ReadAppSetting("dialect", "NHibernate.Dialect.MySQLDialect"));
                properties.Add("connection.connection_string", ApplicationSetting.ReadAppSetting("connection.connection_string", "server=114.215.144.123;database=zjwdb_170792;uid=root;pwd=violante3.141592615927;"));

            }

            ((InPlaceConfigurationSource)source).Add(typeof(ActiveRecordBase), properties);

            return source;
        }

        public static void Evit(object obj)
        {
            if (System.Web.HttpContext.Current != null)
            {
                SessionScope scope = System.Web.HttpContext.Current.Items[Constants.NH_SESSIONSCOPE] as SessionScope;

                if (scope != null && obj != null)
                {
                    scope.Evict(obj);
                }
            }
        }

        public static void Evit<T>(IList<T> objs)
        {
            if (System.Web.HttpContext.Current != null)
            {
                SessionScope scope = System.Web.HttpContext.Current.Items[Constants.NH_SESSIONSCOPE] as SessionScope;
                foreach (var obj in objs)
                {
                    scope.Evict(obj);
                }
            }
        }

        public static ISession GetSession<T>()
        {
            return ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(T));
        }

        public static Logger Logger
        {
            get
            {
                if (_logger == null)
                    _logger = new Logger();
                return _logger;
            }
        }
    }
}
